package org.aphelie.torg.ruler.internal.core.character;

import java.util.ArrayList;

import org.aphelie.torg.ruler.core.IModelChangedEvent;
import org.aphelie.torg.ruler.core.character.ICharacterElement;
import org.aphelie.torg.ruler.core.character.ICharacterObject;
import org.aphelie.torg.ruler.core.character.ICharacterParent;
import org.aphelie.torg.ruler.internal.core.TGRCoreMessages;
import org.eclipse.core.runtime.CoreException;


public abstract class CharacterParent extends IdentifiableCharacterObject implements ICharacterParent {
    private static final long serialVersionUID = 1L;
    protected ArrayList fChildren = null;

    public CharacterParent() {
    }

    public void add(int index, ICharacterObject child) throws CoreException {
        ensureModelEditable();
        getChildrenList().add(index, child);
        postAdd(child);
    }

    public void add(ICharacterObject child) throws CoreException {
        ensureModelEditable();
        getChildrenList().add(child);
        postAdd(child);
    }

    void appendChild(ICharacterElement child) {
        getChildrenList().add(child);
    }

    protected void postAdd(ICharacterObject child) {
        ((CharacterObject) child).setInTheModel(true);
        ((CharacterObject) child).setParent(this);
        fireStructureChanged(child, IModelChangedEvent.INSERT);
    }

    public int getChildCount() {
        return getChildrenList().size();
    }

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (obj instanceof ICharacterParent) {
            ICharacterParent target = (ICharacterParent) obj;
            if (target.getChildCount() != getChildCount())
                return false;
            ICharacterObject[] tchildren = target.getChildren();
            for (int i = 0; i < tchildren.length; i++) {
                ICharacterObject tchild = tchildren[i];
                ICharacterObject child = (ICharacterObject) getChildrenList().get(i);
                if (child == null || child.equals(tchild) == false)
                    return false;
            }
            return true;
        }
        return false;
    }

    public int getIndexOf(ICharacterObject child) {
        return getChildrenList().indexOf(child);
    }

    public void swap(ICharacterObject child1, ICharacterObject child2) throws CoreException {
        ensureModelEditable();
        int index1 = getChildrenList().indexOf(child1);
        int index2 = getChildrenList().indexOf(child2);
        if (index1 == -1 || index2 == -1)
            throwCoreException(TGRCoreMessages.CharacterParent_siblingsNotFoundException);
        getChildrenList().set(index2, child1);
        getChildrenList().set(index1, child2);
        firePropertyChanged(this, P_SIBLING_ORDER, child1, child2);
    }

    public ICharacterObject[] getChildren() {
        return (ICharacterObject[]) getChildrenList().toArray(new ICharacterObject[getChildrenList().size()]);
    }

    public void remove(ICharacterObject child) throws CoreException {
        ensureModelEditable();
        getChildrenList().remove(child);
        ((CharacterObject) child).setInTheModel(false);
        fireStructureChanged(child, IModelChangedEvent.REMOVE);
    }

    protected ArrayList getChildrenList() {
        if (fChildren == null)
            fChildren = new ArrayList(1);
        return fChildren;
    }

}
